package com.xiaoc.bulldozer.common.util;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wj on 2019/5/5.
 */
@Component
public class UrlMappingUtils implements ApplicationListener<ContextRefreshedEvent> {

    private static  Logger logger = LoggerFactory.getLogger(UrlMappingUtils.class);

    private static List<Map<String, Object>> urlInfoList;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext applicationContext = event.getApplicationContext();
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> mappingInfoMap = mapping.getHandlerMethods();
        List<Map<String, Object>> tmpUrlInfoList = new ArrayList<>();

        for (Map.Entry<RequestMappingInfo, HandlerMethod> handlerMethodEntry : mappingInfoMap.entrySet()) {
            Map<String, Object> map1 = new HashMap<>(10);
            RequestMappingInfo info = handlerMethodEntry.getKey();
            HandlerMethod method = handlerMethodEntry.getValue();
            PatternsRequestCondition p = info.getPatternsCondition();
            for (String url : p.getPatterns()) {
                map1.put("url", url);
            }
            map1.put("className", method.getMethod().getDeclaringClass().getName());
            map1.put("method", method.getMethod());
            tmpUrlInfoList.add(map1);
        }
        urlInfoList = tmpUrlInfoList;
        logger.info("urlInfoList:{}", urlInfoList);
    }


    public static Method getMethodByUrl(String requestUrl){
        if(urlInfoList == null) {
            return null;
        }
        for(Map<String, Object> urlInfo : urlInfoList) {
            String url = (String) urlInfo.get("url");
            if(StringUtils.equals(StringUtils.removeEnd(url, "/"), StringUtils.removeEnd(requestUrl, "/"))) {
                return (Method) urlInfo.get("method");
            }
        }

        return null;

    }
}
